package main

import (
	"context"
	"fmt"
	"github.com/coreos/etcd/clientv3"
	"github.com/coreos/etcd/mvcc/mvccpb"
	"github.com/gin-gonic/gin"
	"google.golang.org/grpc"
	"io"
	"math/rand"
	"os"
	"sync"
	"time"
)

var etcd *clientv3.Client

var stockOut sync.Map

var prefix = "/goods/stock/"

func init() {
	var err error
	etcd, err = clientv3.New(clientv3.Config{
		Endpoints:   []string{"39.100.58.10:2379"},
		DialTimeout: 3 * time.Second,
		DialOptions: []grpc.DialOption{grpc.WithBlock()},
	})

	if err != nil {
		fmt.Println(err)
	}

	//defer etcd.Close()
	go watch()
}

func watch() {
	// 监控目录
	kv := clientv3.NewKV(etcd)
	getResponse, err := kv.Get(context.TODO(), prefix, clientv3.WithPrefix())
	if err != nil {
		panic(err)
	}

	for _, item := range getResponse.Kvs {
		fmt.Println("获取数据：", string(item.Key), string(item.Value))
	}

	startRevision := getResponse.Header.Revision + 1
	watcher := clientv3.NewWatcher(etcd)

	watchResponseChan := watcher.Watch(context.TODO(), prefix, clientv3.WithPrefix(), clientv3.WithRev(startRevision))

	for res := range watchResponseChan {
		for _, event := range res.Events {
			switch event.Type {
			case mvccpb.PUT:
				fmt.Println("更新为：", "Value:", string(event.Kv.Value), "Revision:", event.Kv.CreateRevision, event.Kv.ModRevision)
				stockOut.Store("1", "test")
			case mvccpb.DELETE:
				fmt.Println("删除了：", "Value:", string(event.Kv.Value), "Key:", string(event.Kv.Key), "Revision:", event.Kv.ModRevision)
				key := string(event.Kv.Key)[len(prefix):]
				fmt.Println(key)
				stockOut.Delete("1")
			}
		}
	}

}

func main() {

	rand.Seed(time.Now().UnixNano())

	gin.SetMode(gin.ReleaseMode)
	f, _ := os.Create("gin.log")
	gin.DefaultWriter = io.MultiWriter(f)

	r := gin.Default()
	r.GET("/put", func(c *gin.Context) {

		kv := clientv3.NewKV(etcd)
		_, err := kv.Put(context.TODO(),prefix + "1", "1")
		if err != nil {
			fmt.Println("put failed, err:", err)
		}

		c.JSON(200, gin.H{
			"err": err,
		})
	})

	r.GET("/get", func(c *gin.Context) {

		var sign interface{}
		if v, ok := stockOut.Load("1"); ok {
			sign = v
		}

		c.JSON(200, gin.H{
			"sign": sign,
		})
	})

	r.GET("/delete", func(c *gin.Context) {

		kv := clientv3.NewKV(etcd)
		_, err := kv.Delete(context.TODO(),prefix + "1")
		if err != nil {
			fmt.Println("failed, err:", err)
			return
		}

		c.JSON(200, gin.H{
			"err": err,
		})
	})

	r.Run()
}
